﻿using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Provenance.Domain.BaseFiledClass;

namespace Provenance.Write.Api.interceptor
{
    /// <summary>
    /// 实体审计拦截器
    /// </summary>
    public class EntityAuditInterceptor:SaveChangesInterceptor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        public EntityAuditInterceptor(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }
        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
        {
            TrackChanges(eventData);
            return base.SavingChanges(eventData, result);
        }
        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData data,InterceptionResult<int> result,CancellationToken cancellationToken =default)
        {
            TrackChanges(data);
            return base.SavingChangesAsync(data, result, cancellationToken);
        }
        private void TrackChanges(DbContextEventData eventData)
        {
            //检查参数是否为空，为空则抛出异常
            ArgumentNullException.ThrowIfNull(eventData.Context);
            //ChangeTracker 属性负责跟踪实体变化
            //Entries()方法返回所有跟踪的实体
            //DetectChanges()检查实体变化并更新
            eventData.Context.ChangeTracker.DetectChanges();

            foreach(var entry in eventData.Context.ChangeTracker.Entries())
            {
                //entry.Entity是否实现IAuditable接口,如果实现把entry.Entity转换为IAuditable类型,并把结果赋值给auditable
                if (entry.Entity is IAuditable auditable)
                {
                    switch(entry.State)
                    {
                        case EntityState.Added:
                            UpdateAuditFields(auditable, "Create");
                            break;
                        case EntityState.Modified:
                            UpdateAuditFields(auditable, "Update");
                            break;
                        case EntityState.Deleted:
                            UpdateAuditFields(auditable, "Delete");
                            entry.State=EntityState.Modified;
                            break;
                    }   
                }
            }
        }
        /// <summary>
        /// 更新审计字段值
        /// </summary>
        /// <param name="auditable"></param>
        /// <param name="action"></param>
        private void UpdateAuditFields(IAuditable auditable,string action)
        {
            //UTC 是一种时间标准，获取全球一致的时间
            var currentTime = DateTime.UtcNow;
            int userId = _httpContextAccessor.HttpContext?.User.FindFirst(type: ClaimTypes.NameIdentifier)?.Value == null ? 0 : int.Parse(_httpContextAccessor.HttpContext?.User.FindFirst(type: ClaimTypes.NameIdentifier)?.Value!);

            string UserName =_httpContextAccessor.HttpContext?.User.FindFirst(type: ClaimTypes.Name)?.Value??"";
            switch(action)
            {
                case "Update":
                    auditable.ModifyOperatorId=userId;
                    auditable.ModifyOperatorName=UserName;
                    auditable.ModifyDate = currentTime;
                    break;
                case "Create":
                    auditable.CreateOperatorId = userId;
                    auditable.CreateOperatorName = UserName;
                    auditable.CreateDate = currentTime;
                    break;
                case "Delete":
                    auditable.IsDeleted = true;
                    auditable.DeleteOperatorId = userId;
                    auditable.DeleteOperatorName = UserName;
                    auditable.DeleteDate = currentTime;
                    break;
            }
        }



    }
}
